package other.edan.system.k3;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.ScheduleJob;
import com.rkhd.platform.sdk.api.annotations.RequestMethod;
import com.rkhd.platform.sdk.api.annotations.RestApi;
import com.rkhd.platform.sdk.api.annotations.RestMapping;
import com.rkhd.platform.sdk.api.annotations.RestQueryParam;
import com.rkhd.platform.sdk.data.model.OrderDetails__c;
import com.rkhd.platform.sdk.data.model.Product;
import com.rkhd.platform.sdk.data.model.SalesOrder__c;
import com.rkhd.platform.sdk.data.model.SyncConfig__c;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.AsyncTaskException;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.model.BatchOperateResult;
import com.rkhd.platform.sdk.model.OperateResult;
import com.rkhd.platform.sdk.model.QueryResult;
import com.rkhd.platform.sdk.param.ScheduleJobParam;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XoqlService;
import com.rkhd.platform.sdk.task.FutureTask;
import org.apache.commons.lang.StringUtils;
import other.edan.system.client.EdanK3Utils;
import other.edan.system.utils.*;

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Description 同步K3销售订单
 * @Author 黎炎松
 * 2024-08-30 10:20
 */
@RestApi(baseUrl = "/xsy/salesOrder")
public class SyncSalesOrder extends SyncSuper implements ScheduleJob, FutureTask {
    private static XoqlService xoqlService = XoqlService.instance();
    private static final Logger logger = LoggerFactory.getLogger();
    private static String LOGGER_MSG = "同步K3销售订单 ==> ";

    // 执行定时任务
    @Override
    public void execute(ScheduleJobParam scheduleJobParam) {
        logger.debug(LOGGER_MSG + " 执行定时任务开始");
        try {
            String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
            logger.info(LOGGER_MSG + "异步ID:" + messageId);
        } catch (Exception e) {
            logger.error(LOGGER_MSG + " ----- 发生异常：" + e.getMessage());
        }
    }

    // 执行异步函数
    @Override
    public void execute(String s) throws ScriptBusinessException {
        startSyncSalesOrder("");
    }

    /**
     * 根据产品编号手动触发产品同步
     * @param
     * @return
     */
    @RestMapping(value = "/syncById", method = RequestMethod.POST)
    public String syncById(@RestQueryParam(name = "id") Long orderId, @RestQueryParam(name = "fbillNo") String fbillNo) {

        logger.debug("根据编号手动触发同步: fbillNo " + fbillNo);
        if (StringUtils.isNotBlank(fbillNo)) {
            return startSyncSalesOrder(fbillNo);
        }

        // 获取产品的编码
        logger.debug("根据订单编号手动触发订单同步: " + orderId);
        SalesOrder__c salesOrder = new SalesOrder__c();
        salesOrder.setId(orderId);
        salesOrder = HCXObjectService.get(salesOrder);
        String seorderNo = salesOrder.getName();

        logger.debug("根据订单编号手动触发订单同步: " + seorderNo);
        return startSyncSalesOrder(seorderNo);
    }

    /**
     * 手动触发产品同步
     * @param
     * @return
     */
    @RestMapping(value = "/handerSync", method = RequestMethod.POST)
    public String handerSync() throws AsyncTaskException {
        logger.debug("手动触发订单同步");
        String messageId = FutureTaskService.instance().addFutureTask(getClass(), "");
        logger.info(LOGGER_MSG + "异步ID:" + messageId);
        return TfReturnMsgTools.getSuccessResult("Start synchronizing data");
    }


    public static void main(String[] args) throws ApiEntityServiceException {
        //new SyncSalesOrder().startSyncSalesOrder("");
        HCXObjectService.isLocal = true;
        new SyncSalesOrder().startSyncSalesOrder("SEORD012736");
    }

    /**
     * 开始同步产品数据
     */
    public String startSyncSalesOrder(String seorderNo) {
        try {
            logger.debug(LOGGER_MSG + "处理开始");

            // 从数据配置表中获取数据
            String sql = "select id,lastSyncTime__c,syncAssistVal__c from syncConfig__c where syncKey__c = 'K3_XXDD'";
            SyncConfig__c syncConfig = HCXObjectService.queryOne(sql);
            logger.debug(LOGGER_MSG + " syncConfig = " + syncConfig);
            if (syncConfig == null) {
                logger.debug(LOGGER_MSG + " 数据配置信息不存在");
                return TfReturnMsgTools.getFailResult("Data configuration information does not exist");
            }

            // 获取同步时间
            String startDate = syncConfig.getLastSyncTime__c();
            String endDate = HCDateUtils.dateToString(new Date(), HCDateUtils.FORMATTIME); // 同步结束时间
            if (StringUtils.isBlank(startDate)) {
                // 如果为空则退回1天前
                startDate = HCDateUtils.getDaysBeforeString(1, HCDateUtils.FORMATTIME);
            }


            // 设置参数
            Map<String, Object> paramsMap = new HashMap<>();
            paramsMap.put("page", "1");
            paramsMap.put("pageSize", "100");
            // 销售订单号如果不为空 则只查询单条数据
            if (StringUtils.isNotBlank(seorderNo)) {
                paramsMap.put("seorderNo", seorderNo);
            } else {
                // todo
                startDate = "2022-01-20 00:00:00";
                endDate = "2024-08-30 00:00:00";
                paramsMap.put("StartDate", startDate);
                paramsMap.put("EndDate", endDate);
            }
            logger.debug(LOGGER_MSG + " paramsMap: " + paramsMap);

            // 发送请求获取数据
            // todo (去除token)
            ResultBody response = EdanK3Utils.sendGet(paramsMap, EdanK3Utils.GET_SALES_ORDER_URL, "28fec361-9e85-4570-abdf-97b7f3472768");
            if (!Objects.equals(response.getCode(), "200")) {
                logger.debug(LOGGER_MSG + "查询k3销售订单数据异常: " + response.getMessage());
                return TfReturnMsgTools.getFailResult("Abnormal query of k3 sales order data: " + response.getMessage());
            }

            // 获取数据 判断是否有值
            JSONObject result = (JSONObject) response.getResult();
            List<JSONObject> orderList = JSONObject.parseArray(result.getJSONArray("seorderInfos").toJSONString(), JSONObject.class);
            logger.debug(LOGGER_MSG + "查询返回的数据: " + orderList.size());
            if (orderList.size() <= 0) {
                logger.debug(LOGGER_MSG + "暂无需要处理的数据");
                // 同步修改配置表
                upSysConfig(syncConfig, endDate, 0);
                return TfReturnMsgTools.getSuccessResult("There is no data that needs to be synchronized");
            }


            // 按照订单号进行分组
            Map<String, List<JSONObject>> orderListMap = orderList.stream().collect(Collectors.groupingBy(e -> e.getString("fbillNo")));
            logger.debug(LOGGER_MSG + "orderListMap: " + orderListMap);

            // 获取选项集
            JSONObject salesOrderDesc = ComUtils.getEntityDesc("salesOrder__c");
            Map<String, String> planTypeOpt = ComUtils.getMapsFromDescribeJson(salesOrderDesc, "panType__c", false); // 计划类别
            Map<String, String> settleOpt = ComUtils.getMapsFromDescribeJson(salesOrderDesc, "settlementMethod__c", false); // 计算方式
            Map<String, String> saleStyleOpt = ComUtils.getMapsFromDescribeJson(salesOrderDesc, "salesMethod__c", false); // 销售方式
            Map<String, String> salesTypeOpt = ComUtils.getMapsFromDescribeJson(salesOrderDesc, "salesType__c", false); // 销售类型
            Map<String, String> ticketTypeOpt = ComUtils.getMapsFromDescribeJson(salesOrderDesc, "ticketType__c", "apiKey", "label"); // 票种 (使用key进行匹配)
            Map<String, String> contractPaymentOpt = ComUtils.getMapsFromDescribeJson(salesOrderDesc, "contractPayment__c", false); // 合同付款期

            // 获取查询的参数
            Set<String> userNameSet = new HashSet<>(); // 用户
            Set<String> fbillNoSet = new HashSet<>();
            Set<String> primaryKeySet = new HashSet<>();
            Set<String> prdNumberSet = new HashSet<>();
            Set<String> accountSet = new HashSet<>();
            for (JSONObject order : orderList) {
                userNameSet.add("'" + order.getString("declaretor") + "'"); // 跟单员
                userNameSet.add("'" + order.getString("salor") + "'"); // 业务员
                fbillNoSet.add("'" + order.getString("fbillNo") + "'"); // 订单编码
                primaryKeySet.add("'" + order.getString("finterID") + "_" + order.getString("fentryID") + "'"); // 订单明细key
                prdNumberSet.add("'" + order.getString("prdNumber") + "'"); // 产品编码
                accountSet.add("'" + order.getString("customerCode") + "'"); // 客户
            }

            // todo 需要调整为编码 获取系统中的用户id
            String userNames = StringUtils.join(userNameSet, ",");
            sql = String.format("select id,name from user where name in (%s)", userNames);
            Map<String, Long> userMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e1 -> e1.getString("name"), e2 -> e2.getLong("id")));
            logger.debug(LOGGER_MSG + "userMap: " + userMap);

            // 获取系统中存在的销售订单
            String fbillNos = StringUtils.join(fbillNoSet, ",");
            sql = "select id,name from salesOrder__c where name in (" + fbillNos + ")";
            Map<String, Long> crmOrderMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e -> e.getString("name"), e1 -> e1.getLong("id")));
            logger.debug(LOGGER_MSG + "crmOrderMap: " + crmOrderMap);

            // 获取系统中存在的销售订单明细 finterID + "_" + fentryID
            String primaryKeys = StringUtils.join(primaryKeySet, ",");
            sql = "select id,edanId__c from orderDetails__c where edanId__c in (" + primaryKeys + ")";
            Map<String, Long> crmOrderDetailMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e -> e.getString("edanId__c"), e1 -> e1.getLong("id")));
            logger.debug(LOGGER_MSG + "crmOrderDetailMap: " + crmOrderDetailMap);

            // 获取系统中的产品
            String prdNumbers = StringUtils.join(prdNumberSet, ",");
            sql = String.format("select id,FNumber__c from product where FNumber__c in (%s)", prdNumbers);
            Map<String, Long> prdNumberMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e1 -> e1.getString("FNumber__c"), e2 -> e2.getLong("id")));
            logger.debug(LOGGER_MSG + "prdNumberMap: " + prdNumberMap);

            // 获取系统中的客户
            String accounts = StringUtils.join(accountSet, ",");
            sql = String.format("select id,customerCodeNumber__c from account where customerCodeNumber__c in (%s)", accounts);
            Map<String, Long> accountMap = xoqlService.query(sql, true).getRecords().stream().collect(Collectors.toMap(e1 -> e1.getString("customerCodeNumber__c"), e2 -> e2.getLong("id")));
            logger.debug(LOGGER_MSG + "accountMap: " + accountMap);

            // 获取新增、修改的数据
            List<SalesOrder__c> upOrderList = new ArrayList<>(); // 修改订单
            List<OrderDetails__c> upOrderDetailList = new ArrayList<>(); // 修改订单详情
            for (String fbillNo : orderListMap.keySet()) {
                // 明细数据
                List<JSONObject> orderDetailList = orderListMap.get(fbillNo);
                if (orderDetailList.size() <= 0) {
                    continue;
                }

                // 处理销售订单主表
                JSONObject orderObject = orderDetailList.get(0); // 销售订单数据
                SalesOrder__c salesOrder = new SalesOrder__c();
                salesOrder.setEntityType(3422984911002137L);
                String finterID = orderObject.getString("finterID");
                salesOrder.setEdanId__c(finterID);
                salesOrder.setName(fbillNo); // 订单编号
                salesOrder.setPanType__c(ComUtils.getOptVal(planTypeOpt, orderObject.getString("planCategory"))); // 计划类别 planCategory（返回的是: 标准）
                salesOrder.setInvoiceMailing__c(getDateVal(orderObject.getString("invoiceDate"))); // 发票邮寄时间
                salesOrder.setFinancialInvoice__c(orderObject.getString("invoiceNo")); // 财务发票代码
                salesOrder.setInvoice__c(getIsYes(orderObject.getString("isInvoice"))); // 是否开票  1 是 2 否
                salesOrder.setCustomer__c(accountMap.get(orderObject.getString("customerCode"))); // 购货单位 customer
                salesOrder.setSettlementMethod__c(ComUtils.getOptVal(settleOpt, orderObject.getString("settle"))); // 计算方式 settle
                salesOrder.setSalesTerritory__c(orderObject.getString("saleRegion")); // 销售区域
                salesOrder.setCountrySale__c(orderObject.getString("country")); // 销售国家
                salesOrder.setSalesMethod__c(ComUtils.getOptVal(saleStyleOpt, orderObject.getString("saleStyle"))); // 销售方式 saleStyle
                salesOrder.setConsignee__c(orderObject.getString("address")); // 收货地址
                salesOrder.setConsignee__c(orderObject.getString("consignee")); // 收货人
                salesOrder.setConsigneeContact__c(orderObject.getString("tel")); // 收货人联系电话
                salesOrder.setSalesType__c(ComUtils.getOptVal(salesTypeOpt, orderObject.getString("saleCategory"))); // 销售类型 saleCategory
                salesOrder.setAbstract__c(orderObject.getString("explanation")); // 摘要
                salesOrder.setDate__c(getDateVal(orderObject.getString("fdate"))); // 日期
                salesOrder.setOfficialContractNumber__c(orderObject.getString("contractNumber")); // 正式合同编号
                salesOrder.setForeignAid__c(getIsYes(orderObject.getString("isForeignaid"))); // 是否援外
                salesOrder.setForeignAidCountry__c(orderObject.getString("aidCountry")); // 援外国家
                salesOrder.setContractPayment__c(ComUtils.getOptVal(contractPaymentOpt, orderObject.getString("contractPay"))); // 合同付款期 contractPay
                salesOrder.setContractDate__c(getDateVal(orderObject.getString("signDate"))); // 合同签订日期
                salesOrder.setDeliveryDate__c(orderObject.getString("deliveryDate")); // 发货日期
                salesOrder.setAmountRefund__c(orderObject.getString("returnDate")); // 回款金额
                salesOrder.setReturnContract__c(getIsYes(orderObject.getString("contractReturn"))); // 合同返回
                salesOrder.setContractAcceptance__c(getDateVal(orderObject.getString("acceptDate"))); // 合同接收日期
                salesOrder.setTicketType__c(ComUtils.getOptVal(ticketTypeOpt, orderObject.getString("ticketTypeCode"))); // 票种 ticketType
                salesOrder.setDateDrawing__c(getDateVal(orderObject.getString("ticketDate"))); // 开票日期
                salesOrder.setExchangeRate__c(orderObject.getDouble("exchangeRate")); // 汇率
                salesOrder.setContinentCode__c(orderObject.getString("continentCode")); // 大洲代码
                salesOrder.setContinent__c(orderObject.getString("continent")); // 大洲
                salesOrder.setRegion__c(orderObject.getString("region")); // 区域
                salesOrder.setAreaCode__c(orderObject.getString("regionCode")); // 区域代码
                salesOrder.setMerchandiser__c(userMap.get(orderObject.getString("declaretor"))); // 跟单员 declaretor
                salesOrder.setSalesman__c(userMap.get(orderObject.getString("salor"))); // 业务员 salor
                salesOrder.setDepartment__c(orderObject.getString("department")); // 部门 department
                //salesOrder.setCurrency__c(); // 币别 currency --

                // 判断系统中是否存在，存在则更新
                logger.debug(LOGGER_MSG + "salesOrder = " + salesOrder);
                if (crmOrderMap.containsKey(fbillNo)) {
                    salesOrder.setId(crmOrderMap.get(fbillNo));
                    upOrderList.add(salesOrder);
                    // 进行更新
                    if (upOrderList.size() >= 100) {
                        HCXObjectService.updateBatch(upOrderList);
                        upOrderList.clear();
                    }
                } else {
                    // 新增
                    OperateResult insert = HCXObjectService.insert(salesOrder);
                    if (!insert.getSuccess()) {
                        logger.error(LOGGER_MSG + "新增订单失败 fbillNo: " + fbillNo);
                        continue;
                    }
                    salesOrder.setId(insert.getDataId());
                }

                // 处理订单明细数据 (不考虑k3后续同步删除订单明细的情况)
                for (JSONObject orderDetailObj : orderDetailList) {
                    List<OrderDetails__c> addOrderDetail = new ArrayList<>(); // 新增订单详情

                    // 明细对象
                    String fentryID = orderDetailObj.getString("fentryID");
                    String edanId = finterID + fentryID; // 唯一标识: finterID + fentryID
                    OrderDetails__c orderDetails = new OrderDetails__c();
                    orderDetails.setEntityType(3423047106025928L);
                    orderDetails.setSalesOrder__c(salesOrder.getId()); // 主表
                    orderDetails.setEdanId__c(edanId); // 数据id
                    orderDetails.setName(orderDetailObj.getString("fentryID")); // 编码
                    orderDetails.setProductCode__c(prdNumberMap.get(orderDetailObj.getString("prdNumber"))); // 产品
                    orderDetails.setInvoiceLibrary__c(orderDetailObj.getString("ffpkNumber")); // 发票库对应码
                    orderDetails.setQuantity__c(orderDetailObj.getDouble("qty")); // 数量
                    orderDetails.setUnitPrice__c(orderDetailObj.getDouble("price")); // 单价
                    orderDetails.setTaxUnitprice__c(orderDetailObj.getDouble("priceDiscount")); // 实际含税单价
                    orderDetails.setActualUnitPrice__c(orderDetailObj.getDouble("priceDiscount")); // 实际含税单价
                    orderDetails.setAmount__c(orderDetailObj.getDouble("amount")); // 金额
                    orderDetails.setTaxRate__c(orderDetailObj.getDouble("taxRate")); // 税率
                    orderDetails.setTotalValueTax__c(orderDetailObj.getDouble("allStdAmount")); // 价税合计
                    orderDetails.setSuggestedDeliveryDate__c(getDateVal(orderDetailObj.getString("adviceConsignDate"))); // 建议交货日期
                    orderDetails.setRemark__c(orderDetailObj.getString("note")); // 备注
                    orderDetails.setMachineType__c(orderDetailObj.getString("model")); // 机型

                    // 判断是新增还是修改
                    if (crmOrderDetailMap.containsKey(edanId)) {
                        orderDetails.setId(crmOrderDetailMap.get(edanId));
                        upOrderDetailList.add(orderDetails);
                    } else {
                        addOrderDetail.add(orderDetails);
                    }

                    // 进行新增、编辑操作
                    HCXObjectService.insertBatch(addOrderDetail);
                    if (upOrderDetailList.size() > 100) {
                        HCXObjectService.updateBatch(upOrderDetailList);
                        upOrderDetailList.clear();
                    }
                }
            }

            // 进行批量新增、更新
            HCXObjectService.updateBatch(upOrderList);
            HCXObjectService.updateBatch(upOrderDetailList);

            // 更新同步配置
            if (StringUtils.isBlank(seorderNo)) {
                upSysConfig(syncConfig, endDate, orderListMap.size());
            }

            logger.debug(LOGGER_MSG + "处理成功");
            return TfReturnMsgTools.getSuccessResult("Synchronization successful");
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug(LOGGER_MSG + "处理异常:" + e.getMessage());
            return TfReturnMsgTools.getFailResult("Synchronization exception:" + e.getMessage());
        }
    }



}
